/**
 * Author(s): xuming.Wong <xuming.Wong@gmail.com>
 */

#ifndef __ENVIRONMENT_MANAGER_H__
#define __ENVIRONMENT_MANAGER_H__

#include "AstroTimer.h"
#include "SkyDome.h"
#include "Sun.h"
#include "Moon.h"
#include "CloudSystem.h"
#include "StarField.h"
#include "StarFieldImage.h"
#include "GroundFog.h"

namespace PQEngine
{

	/*This class is used for manage the scene's visable environment.
	The environment in a scene including sky water and weather...
	This class implement the scene's weather simulation.
	*/
	class EnvironmentManager
	{
	public:
		static const Ogre::String ENV_DATA_PATH;
		static const Ogre::String ENV_GROUP_NAME;
	public:
		EnvironmentManager(SceneObject* sceneObject);
		void update(float deltaT);
		void enableSkyDome(bool enabled);
	private:
		void initResource();
		void initEnvironment();
		void initAstroTimer();
		void initSkyDome();
		void initSun();
		void initMoon();
		void initClouds();
		void initStarFeild();

		const Ogre::Vector3 getSunDirection(double julianDay);
		const Ogre::Vector3 getMoonDirection(double julianDay);

		Ogre::Real getMoonPhase(double julianDay);
		Ogre::Real getFogDensity(float time, const Ogre::Vector3 &sunDir);
		Ogre::ColourValue getFogColor(float time, const Ogre::Vector3 &sunDir);
		Ogre::ColourValue getSunColor(float time, const Ogre::Vector3 &sunDir);
		Ogre::ColourValue getMoonLightColor(float time, const Ogre::Vector3 &moonDir);
		Ogre::ColourValue getMoonBodyColor(const Ogre::Vector3 &moonDir);

		const Ogre::Vector3 makeDirection(Ogre::Degree azimuth, Ogre::Degree altitude);

		 /// Get the observer's longitude. East is positive, west is negative.
        inline const Ogre::Degree getObserverLongitude() const { return _observerLongitude; }

        /// Set the observer's longitude. East is positive, west is negative.
        inline void setObserverLongitude (Ogre::Degree value) { _observerLongitude = value; }

        /// Get the observer's latitude. North is positive, south is negative.
        inline const Ogre::Degree getObserverLatitude () const { return mObserverLatitude; }

		/// Gets the current image starfield, or null if disabled.
		inline StarFieldImage* getStarFieldImage() const { return _starFieldImage; }

		/** Gets the color of sun light.
         *  This color is used to illuminate the scene.
         *  @return The color of the sun's light
		 */
		Ogre::ColourValue getSunLightColor(Ogre::Real time, const Ogre::Vector3 &sunDir);

	private:
		SceneObject* _sceneObject;
		Ogre::SceneNode* _cameraNode;
		Ogre::SceneNode* _groundNode;

		AstroTimer* _astroTimer;
		SkyDome* _skyDome;
		Sun* _sun;
		Moon* _moon;
		CloudSystem* _clouds;
		StarField* _starField;
		StarFieldImage* _starFieldImage;

		Ogre::Degree _observerLongitude;
		Ogre::Degree mObserverLatitude;

		Ogre::Image* _skyGradientsImage;
		Ogre::Image* _sunColorImage;

		Ogre::Real _fogDensityMultiplier;
		Ogre::Real _fogColorMultiplier;
		Ogre::Real _groundFogMultiplier;
		Ogre::Real _groundDensityMultiplier;

		GroundFog* _groundFog;
		

	};
}
#endif
